package com.mars.diancan.service.impl;

import com.lly835.bestpay.enums.BestPayResultEnum;
import com.lly835.bestpay.enums.BestPayTypeEnum;
import com.lly835.bestpay.model.PayRequest;
import com.lly835.bestpay.model.PayResponse;
import com.lly835.bestpay.model.RefundRequest;
import com.lly835.bestpay.model.RefundResponse;
import com.lly835.bestpay.service.BestPayService;
import com.lly835.bestpay.service.impl.BestPayServiceImpl;
import com.mars.diancan.common.ResultEnum;
import com.mars.diancan.config.WechatPayConfig;
import com.mars.diancan.dto.OrderDTO;
import com.mars.diancan.exception.DiancanException;
import com.mars.diancan.service.OrderService;
import com.mars.diancan.service.PayService;
import com.mars.diancan.utils.JsonUtil;
import com.mars.diancan.utils.MathUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 *
 * 支付接口实现
 * @author MARS
 * @date 2018/6/28
 */
@Service
@Slf4j
public class PayServiceImpl implements PayService {

    @Autowired
    private BestPayServiceImpl bestPayService;

    @Autowired
    private OrderService orderService;
    /**
     * 发起支付
     * @param orderDTO
     */
    @Override
    public PayResponse create(OrderDTO orderDTO) {
        // liao_获取支付接口
        PayRequest payRequest = new PayRequest();
        payRequest.setOpenid(orderDTO.getBuyerOpenid());
        payRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());
        payRequest.setOrderId(orderDTO.getOrderId());
        payRequest.setOrderName("微信点餐订单");
        // 支付方式
        payRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5);

        log.info("微信发起支付，request={}",JsonUtil.toJson(payRequest));

        PayResponse payResponse = bestPayService.pay(payRequest);

        log.info("微信发起支付，payResponse={}",JsonUtil.toJson(payResponse));

        return payResponse;
    }

    /**
     * 后端支付异步通知
     * 调用liao_best-pay
     *
     * 异步通知需要注意的地方：
     * 1、验证签名
     * 2、支付状态检查
     * 3、支付金额
     * 4、支付人（下单人 == 买家）
     * @param notifyData
     */
    @Override
    public PayResponse notify(String notifyData) {
        PayResponse payResponse = bestPayService.asyncNotify(notifyData);
        log.info("微信支付，异步通知，payResponse={}",payResponse);
        // 修改订单支付状态:
        // - 1.查询订单
        OrderDTO orderDTO = orderService.findOne(payResponse.getOrderId());

        // - 2.判断订单是否存在
        if(orderDTO == null) {
            log.error("微信支付，异步通知，订单不存在，orderId={}",payResponse.getOrderId());
            throw new DiancanException(ResultEnum.ORDER_NOT_EXIST);
        }

        // - 3.判断金额是否一致
        //     -- 数值的比较：最好不要使用double比较，会因为精度出错
        //     -- 使用BigDecimal 的 compareTo()，进行比较
        if (!MathUtil.equals(payResponse.getOrderAmount(),orderDTO.getOrderAmount().doubleValue())) {
            log.error("微信支付，异步通知，订单金额不一致，orderId={},微信通知金额={},系统订单金额={}",
                    payResponse.getOrderId(),
                    payResponse.getOrderAmount(),
                    orderDTO.getOrderAmount());
            throw new DiancanException(ResultEnum.WXPAY_NOTIFY_MONEY_WERIFY_ERROR);

        }
        // - 4.以上均通过后，才能修改支付状态
        orderService.paid(orderDTO);
        return payResponse;
    }

    /**
     * 微信退款：
     * 1.下载证书，将证书放置指定位置：  keyPath:的路径为证书的存放路径
     * @param orderDTO
     */
    @Override
    public RefundResponse refund(OrderDTO orderDTO) {
        RefundRequest refundRequest = new RefundRequest();
        refundRequest.setOrderId(orderDTO.getOrderId());
        refundRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());
        refundRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5);
        log.info("微信退款，request={}",refundRequest);
        RefundResponse refundResponse =  bestPayService.refund(refundRequest);
        log.info("微信退款，response={}",refundResponse);
        return refundResponse;
    }
}
